package utils

import (
	"bytes"
	"fmt"
	log "github.com/go-admin-team/go-admin-core/logger"
	"runtime"
)

var panicStart = []byte("/src/runtime/panic.go")
var lineEnd = []byte("\n")

func Try(action func(), catch func(err error)) {
	defer func() {
		if e := recover(); e != nil {
			if catch != nil {
				var errStr string
				if err, ok := e.(error); ok {
					errStr = err.Error()
				} else {
					errStr = fmt.Sprint(e)
				}
				var alloc [2048]byte
				stack := alloc[:]
				n := runtime.Stack(stack, false)
				stack = stack[:n]
				start := bytes.Index(stack, panicStart)
				if start >= 0 {
					stack = stack[start:]
					start = bytes.Index(stack, lineEnd) + 1
					stack = stack[start:]
				}
				err := fmt.Errorf("%s at %s", errStr, stack)
				catch(err)
			}
		}
	}()
	action()
}

// Go 使用try执行goroutine, 防止崩溃
func Go(action func()) {
	go Try(action, func(err error) {
		log.Error("go panic", "err", err.Error())
	})
}
